package com.wisecoach.gatewayplus.transaction.sync;

import com.wisecoach.gatewayplus.bind.ContractArgs;
import com.wisecoach.gatewayplus.bind.ContractCommand;
import com.wisecoach.gatewayplus.transaction.ChaincodeException;
import com.wisecoach.gatewayplus.transaction.ContractExecutor;
import com.wisecoach.gatewayplus.transaction.TransactionStrategy;
import com.wisecoach.util.CollectionUtils;
import org.hyperledger.fabric.client.*;

/**
 * 为了实现 {@link TransactionStrategy#SUBMIT_ASYNC}策略的合同执行器
 * {@code @author:} wisecoach
 * {@code @date:} 2023/3/4 下午7:15
 * {@code @version:} 1.0.0
 */


public class SubmitSyncContractExecutor implements ContractExecutor {

    /**
     * evaluate只需要正常地调用evaluate即可
     * @param contract 要执行的链码对象
     * @param command 要执行的链码信息
     * @param args 链码交易参数
     */
    @Override
    public byte[] evaluate(Contract contract, ContractCommand command, ContractArgs args) {
        try {
            Proposal.Builder builder = contract.newProposal(command.getTransactionName());
            if (!CollectionUtils.isEmpty(args.getTransientMap())) {
                builder.putAllTransient(args.getTransientMap());
            }
            Proposal proposal = builder.addArguments(args.getArgs()).build();
            return proposal.evaluate();
        } catch (GatewayException e) {
            throw new ChaincodeException("链码执行失败", e);
        }
    }

    /**
     * 直接背书异步提交
     * @param contract 要执行的链码对象
     * @param command 要执行的链码信息
     * @param args 链码交易参数
     * @return 链码执行结果
     */
    @Override
    public byte[] submit(Contract contract, ContractCommand command, ContractArgs args) {
        try {
            Proposal.Builder builder = contract.newProposal(command.getTransactionName());
            if (!CollectionUtils.isEmpty(args.getTransientMap())) {
                builder.putAllTransient(args.getTransientMap());
            }
            Proposal proposal = builder.addArguments(args.getArgs()).build();
            Transaction transaction = proposal.endorse();
            return transaction.submit();
        } catch (EndorseException | SubmitException e) {
            throw new ChaincodeException("链码执行失败", e);
        } catch (CommitException | CommitStatusException e) {
            throw new RuntimeException(e);
        }
    }
}
